#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

namespace ns_protocol
{
// #define MYSELF 1

#define SPACE " " // 多少个空格或者其它符号
#define SPACE_LEN strlen(SPACE)
#define SEP "\r\n" // 分隔符
#define SEP_LEN strlen(SEP) // 不能是sizeof

    // 1. 自主实现序列化的格式: "length\r\n_x _op _y\r\n" (约定/协议)
    class Request // 请求, 现在即要运算的式子
    {
    public:
        std::string Serialize() // 序列化
        {
#ifdef MYSELF
            std::string str;
            str = std::to_string(_x);
            str += SPACE;
            str += _op;
            str += SPACE;
            str += std::to_string(_y);
            return str;
#else
// 另一种序列化反序列化方案
            Json::Value root; // 万能对象
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::FastWriter writer;
            return writer.write(root); // 返回值是序列化好的结果,直接return
#endif
        }

        // "_x _op _y"
        // "1234 + 5678"
        bool Deserialized(const std::string &str) // 反序列化
        {
#ifdef MYSELF
            std::size_t left = str.find(SPACE); // 找空格
            if (left == std::string::npos)
                return false;
            std::size_t right = str.rfind(SPACE);
            if (right == std::string::npos)
                return false;
            _x = atoi(str.substr(0, left).c_str()); // 截取子串,前闭后开
            _y = atoi(str.substr(right + SPACE_LEN).c_str());
            if (left + SPACE_LEN > str.size())
                return false;
            else
                _op = str[left + SPACE_LEN];
            return true;
#else
// 另一种序列化反序列化方案
            Json::Value root; // 继续定义万能Value对象
            Json::Reader reader; // 定义Reader对象
            reader.parse(str, root); // 调用parse,传入序列化好的字符串str和万能对象
            _x = root["x"].asInt(); // 拿到key值"x"对应的val,asInt是当做整数的意思
            _y = root["y"].asInt();
            _op = root["op"].asInt(); // char类型的本质也是整数
            return true;
#endif
        }

    public:
        Request()
        {}
        Request(int x, int y, char op) 
            : _x(x)
            , _y(y)
            , _op(op)
        {}
        ~Request() 
        {}

    public: // 如果私有就要写get函数了，下面也不私有了
        // 约定
        int _x;
        int _y;
        char _op; // '+' '-' '*' '/' '%'
    };

    class Response // 应答, 现在即要运算的式子+结果
    {
    public:
        // "_code _result"
        std::string Serialize() // 序列化
        {
#ifdef MYSELF
            std::string s;
            s = std::to_string(_code);
            s += SPACE;
            s += std::to_string(_result);
            return s;
#else
// 另一种序列化反序列化方案
            Json::Value root; // 和Request的步骤一样
            root["code"] = _code;
            root["result"] = _result;
            root["xx"] = _x;
            root["yy"] = _y;
            root["zz"] = _op;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }

        // "6912 0"
        bool Deserialized(const std::string &s) // 反序列化
        {
#ifdef MYSELF
            std::size_t pos = s.find(SPACE);
            if (pos == std::string::npos)
                return false;
            _code = atoi(s.substr(0, pos).c_str());
            _result = atoi(s.substr(pos + SPACE_LEN).c_str());
            return true;
#else
// 另一种序列化反序列化方案
            Json::Value root; // 和Request的步骤一样
            Json::Reader reader;
            reader.parse(s, root);
            _code = root["code"].asInt();
            _result = root["result"].asInt();
            _x =  root["xx"].asInt();
            _y =  root["yy"].asInt();
            _op =  root["zz"].asInt();
            return true;
#endif
        }

    public:
        Response()
        {}
        Response(int result, int code, int x, int y, char op) 
            : _result(result)
            , _code(code)
            , _x(x)
            , _y(y)
            , _op(op)
        {}
        ~Response() 
        {}

    public:
        // 约定
        int _result; // 计算结果
        int _code;   // 计算结果的状态码
        int _x;
        int _y;
        char _op;
    };

    bool Recv(int sock, std::string *out) // 读取数据, 返回一个完整的报文
    {
        // UDP是面向数据报, TCP 面向字节流的:
         char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer)-1, 0); // 9\r\n123+789\r\n
        if (s > 0)
        {
            buffer[s] = 0;
            *out += buffer;
        }
        else if (s == 0)
            return false;
        else
            return false;
        return true;
    }

    void Send(int sock, const std::string str) // 发送数据
    {
        int n = send(sock, str.c_str(), str.size(), 0);
        if (n < 0)
            std::cout << "send error" << std::endl;
    }

    //读取到的各种情况: "length\r\n_x _op _y\r\n..." // 10\r\nabc // "_x _op _y\r\n length\r\nXXX\r\n"
    std::string Decode(std::string &buffer) // 协议解析，保证得到一个完整的报文
    {
        std::size_t pos = buffer.find(SEP); // 找分隔符
        if(pos == std::string::npos) 
            return "";
        int size = atoi(buffer.substr(0, pos).c_str());
        int surplus = buffer.size() - pos - SEP_LEN * 2; // 读取到的有效长度(剩余)
        if(surplus >= size) // 至少具有一个合法完整的报文, 可以提取了
        {
            buffer.erase(0, pos + SEP_LEN);
            std::string s = buffer.substr(0, size);
            buffer.erase(0, size + SEP_LEN);
            return s;
        }
        else
            return "";
    }

    std::string Encode(std::string &s) // 添加长度信息，形成一个完整的报文
    {   // "XXXXXxX" -> "7\r\nXXXxXXX\r\n"
        std::string new_package = std::to_string(s.size());
        new_package += SEP;
        new_package += s;
        new_package += SEP;
        return new_package;
    }
}